package com.imut.lagain.repository;
import org.slf4j.LoggerFactory;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imut.lagain.entity.AccessLog;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 访问日志数据访问层
 */
@Mapper
public interface AccessLogRepository extends BaseMapper<AccessLog> {
    
    /**
     * 根据用户ID查询访问日志
     * @param userId 用户ID
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE user_id = #{userId} ORDER BY access_time DESC")
    IPage<AccessLog> findByUserId(@Param("userId") Long userId, Page<AccessLog> page);
    
    /**
     * 根据用户ID分页查询访问日志
     * @param userId 用户ID
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE user_id = #{userId} ORDER BY access_time DESC")
    IPage<AccessLog> findByUserIdWithPage(@Param("userId") Long userId, Page<AccessLog> page);
    
    /**
     * 根据访问路径查询日志
     * @param path 访问路径
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE path = #{path} ORDER BY access_time DESC")
    IPage<AccessLog> findByPath(@Param("path") String path, Page<AccessLog> page);
    
    /**
     * 根据访问路径分页查询日志
     * @param path 访问路径
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE path = #{path} ORDER BY access_time DESC")
    IPage<AccessLog> findByPathWithPage(@Param("path") String path, Page<AccessLog> page);
    
    /**
     * 根据请求方法查询日志
     * @param method 请求方法
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE method = #{method} ORDER BY access_time DESC")
    IPage<AccessLog> findByMethod(@Param("method") String method, Page<AccessLog> page);
    
    /**
     * 根据请求方法分页查询日志
     * @param method 请求方法
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE method = #{method} ORDER BY access_time DESC")
    IPage<AccessLog> findByMethodWithPage(@Param("method") String method, Page<AccessLog> page);
    
    /**
     * 根据IP地址查询日志
     * @param ipAddress IP地址
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE ip_address = #{ipAddress} ORDER BY access_time DESC")
    IPage<AccessLog> findByIpAddress(@Param("ipAddress") String ipAddress, Page<AccessLog> page);
    
    /**
     * 根据IP地址分页查询日志
     * @param ipAddress IP地址
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE ip_address = #{ipAddress} ORDER BY access_time DESC")
    IPage<AccessLog> findByIpAddressWithPage(@Param("ipAddress") String ipAddress, Page<AccessLog> page);
    
    /**
     * 根据状态码查询日志
     * @param statusCode 状态码
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE status_code = #{statusCode} ORDER BY access_time DESC")
    IPage<AccessLog> findByStatusCode(@Param("statusCode") Integer statusCode, Page<AccessLog> page);
    
    /**
     * 根据状态码分页查询日志
     * @param statusCode 状态码
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE status_code = #{statusCode} ORDER BY access_time DESC")
    IPage<AccessLog> findByStatusCodeWithPage(@Param("statusCode") Integer statusCode, Page<AccessLog> page);
    
    /**
     * 查询指定时间范围内的访问日志
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime} ORDER BY access_time DESC")
    IPage<AccessLog> findByAccessTimeBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, Page<AccessLog> page);
    
    /**
     * 查询用户在指定时间范围内的访问日志
     * @param userId 用户ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 访问日志列表
     */
    @Select("SELECT * FROM access_log WHERE user_id = #{userId} AND access_time BETWEEN #{startTime} AND #{endTime} ORDER BY access_time DESC")
    List<AccessLog> findByUserIdAndAccessTimeBetween(@Param("userId") Long userId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 查询响应时间超过指定值的日志
     * @param responseTime 响应时间阈值（毫秒）
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE response_time > #{responseTime} ORDER BY response_time DESC")
    IPage<AccessLog> findByResponseTimeGreaterThan(@Param("responseTime") Long responseTime, Page<AccessLog> page);
    
    /**
     * 查询响应时间在指定范围内的日志
     * @param minTime 最小响应时间
     * @param maxTime 最大响应时间
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE response_time BETWEEN #{minTime} AND #{maxTime} ORDER BY response_time DESC")
    IPage<AccessLog> findByResponseTimeBetween(@Param("minTime") Long minTime, @Param("maxTime") Long maxTime, Page<AccessLog> page);
    
    /**
     * 查询错误状态码的访问日志（4xx, 5xx）
     * @param page 分页参数
     * @return 访问日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE status_code >= 400 ORDER BY access_time DESC")
    IPage<AccessLog> findErrorLogs(Page<AccessLog> page);
    
    /**
     * 统计用户访问次数
     * @param userId 用户ID
     * @return 访问次数
     */
    @Select("SELECT COUNT(*) FROM access_log WHERE user_id = #{userId}")
    Long countByUserId(@Param("userId") Long userId);
    
    /**
     * 统计指定路径的访问次数
     * @param path 访问路径
     * @return 访问次数
     */
    @Select("SELECT COUNT(*) FROM access_log WHERE path = #{path}")
    Long countByPath(@Param("path") String path);
    
    /**
     * 统计指定IP的访问次数
     * @param ipAddress IP地址
     * @return 访问次数
     */
    @Select("SELECT COUNT(*) FROM access_log WHERE ip_address = #{ipAddress}")
    Long countByIpAddress(@Param("ipAddress") String ipAddress);
    
    /**
     * 统计指定时间范围内的访问次数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 访问次数
     */
    @Select("SELECT COUNT(*) FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime}")
    Long countByAccessTimeBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 统计用户在指定时间范围内的访问次数
     * @param userId 用户ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 访问次数
     */
    @Select("SELECT COUNT(*) FROM access_log WHERE user_id = #{userId} AND access_time BETWEEN #{startTime} AND #{endTime}")
    Long countByUserIdAndAccessTimeBetween(@Param("userId") Long userId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 统计错误访问次数
     * @return 错误访问次数
     */
    @Select("SELECT COUNT(*) FROM access_log WHERE status_code >= 400")
    Long countErrorAccess();
    
    /**
     * 统计指定状态码的访问次数
     * @param statusCode 状态码
     * @return 访问次数
     */
    @Select("SELECT COUNT(*) FROM access_log WHERE status_code = #{statusCode}")
    Long countByStatusCode(@Param("statusCode") Integer statusCode);
    
    /**
     * 查询最近的访问日志
     * @param limit 限制数量
     * @return 访问日志列表
     */
    @Select("SELECT * FROM access_log ORDER BY access_time DESC LIMIT #{limit}")
    List<AccessLog> findRecentLogs(@Param("limit") Integer limit);
    
    /**
     * 查询用户最近的访问日志
     * @param userId 用户ID
     * @param limit 限制数量
     * @return 访问日志列表
     */
    @Select("SELECT * FROM access_log WHERE user_id = #{userId} ORDER BY access_time DESC LIMIT #{limit}")
    List<AccessLog> findRecentLogsByUserId(@Param("userId") Long userId, @Param("limit") Integer limit);
    
    /**
     * 查询访问路径统计
     * @return 路径访问统计列表（路径，次数）
     */
    @Select("SELECT path, COUNT(*) as count FROM access_log GROUP BY path ORDER BY count DESC")
    List<Object[]> getPathStatistics();
    
    /**
     * 查询IP访问统计
     * @return IP访问统计列表（IP，次数）
     */
    @Select("SELECT ip_address, COUNT(*) as count FROM access_log GROUP BY ip_address ORDER BY count DESC")
    List<Object[]> getIpStatistics();
    
    /**
     * 查询状态码统计
     * @return 状态码统计列表（状态码，次数）
     */
    @Select("SELECT status_code, COUNT(*) as count FROM access_log GROUP BY status_code ORDER BY count DESC")
    List<Object[]> getStatusCodeStatistics();
    
    /**
     * 查询用户访问统计
     * @return 用户访问统计列表（用户ID，次数）
     */
    @Select("SELECT user_id, COUNT(*) as count FROM access_log WHERE user_id IS NOT NULL GROUP BY user_id ORDER BY count DESC")
    List<Object[]> getUserAccessStatistics();
    
    /**
     * 查询平均响应时间
     * @return 平均响应时间（毫秒）
     */
    @Select("SELECT AVG(response_time) FROM access_log WHERE response_time IS NOT NULL")
    Double getAverageResponseTime();
    
    /**
     * 查询指定路径的平均响应时间
     * @param path 访问路径
     * @return 平均响应时间（毫秒）
     */
    @Select("SELECT AVG(response_time) FROM access_log WHERE path = #{path} AND response_time IS NOT NULL")
    Double getAverageResponseTimeByPath(@Param("path") String path);
    
    /**
     * 查询指定时间范围内的平均响应时间
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 平均响应时间（毫秒）
     */
    @Select("SELECT AVG(response_time) FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime} AND response_time IS NOT NULL")
    Double getAverageResponseTimeByTimeBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 查询独立访客数（基于IP）
     * @return 独立访客数
     */
    @Select("SELECT COUNT(DISTINCT ip_address) FROM access_log")
    Long getUniqueVisitorCount();
    
    /**
     * 统计访问次数
     * @param userId 用户ID
     * @param path 路径
     * @param method 方法
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 访问次数
     */
    @Select("SELECT COUNT(*) FROM access_log WHERE (#{userId} IS NULL OR user_id = #{userId}) AND (#{path} IS NULL OR path = #{path}) AND (#{method} IS NULL OR method = #{method}) AND access_time BETWEEN #{startTime} AND #{endTime}")
    Long countAccess(@Param("userId") Long userId, @Param("path") String path, @Param("method") String method, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 统计指定时间范围内的独立访客数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 独立访客数
     */
    @Select("SELECT COUNT(DISTINCT ip_address) FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime}")
    Long countUniqueVisitors(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 查询热门路径
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param limit 限制数量
     * @return 热门路径列表
     */
    @Select("SELECT path, COUNT(*) as count FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime} GROUP BY path ORDER BY count DESC LIMIT #{limit}")
    List<Map<String, Object>> findPopularPaths(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("limit") Integer limit);
    
    /**
     * 查询活跃用户
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param limit 限制数量
     * @return 活跃用户列表
     */
    @Select("SELECT user_id, COUNT(*) as count FROM access_log WHERE user_id IS NOT NULL AND access_time BETWEEN #{startTime} AND #{endTime} GROUP BY user_id ORDER BY count DESC LIMIT #{limit}")
    List<Map<String, Object>> findActiveUsers(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("limit") Integer limit);
    
    /**
     * 删除指定时间之前的访问日志
     * @param beforeTime 时间点
     * @return 删除的记录数
     */
    @Delete("DELETE FROM access_log WHERE access_time < #{beforeTime}")
    int deleteByAccessTimeBefore(@Param("beforeTime") LocalDateTime beforeTime);
    
    /**
     * 修复findErrorLogs方法，添加时间范围参数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param page 分页参数
     * @return 错误日志分页列表
     */
    @Select("SELECT * FROM access_log WHERE status_code >= 400 AND access_time BETWEEN #{startTime} AND #{endTime} ORDER BY access_time DESC")
    IPage<AccessLog> findErrorLogsByTimeBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, Page<AccessLog> page);
    
    /**
     * 统计指定时间范围内路径的访问次数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 路径访问统计
     */
    @Select("SELECT path, COUNT(*) as count FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime} GROUP BY path")
    List<Map<String, Object>> countByPathBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 统计指定时间范围内IP的访问次数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return IP访问统计
     */
    @Select("SELECT ip_address, COUNT(*) as count FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime} GROUP BY ip_address")
    List<Map<String, Object>> countByIpAddressBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 统计指定时间范围内状态码的访问次数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 状态码访问统计
     */
    @Select("SELECT status_code, COUNT(*) as count FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime} GROUP BY status_code")
    List<Map<String, Object>> countByStatusCodeBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 统计指定时间范围内用户的访问次数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 用户访问统计
     */
    @Select("SELECT user_id, COUNT(*) as count FROM access_log WHERE user_id IS NOT NULL AND access_time BETWEEN #{startTime} AND #{endTime} GROUP BY user_id")
    List<Map<String, Object>> countByUserIdBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 获取指定路径在指定时间范围内的平均响应时间
     * @param path 路径
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 平均响应时间
     */
    @Select("SELECT AVG(response_time) FROM access_log WHERE path = #{path} AND access_time BETWEEN #{startTime} AND #{endTime} AND response_time IS NOT NULL")
    Double getAverageResponseTimeByPath(@Param("path") String path, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
    
    /**
     * 查询指定时间范围内的独立访客数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 独立访客数
     */
    @Select("SELECT COUNT(DISTINCT ip_address) FROM access_log WHERE access_time BETWEEN #{startTime} AND #{endTime}")
    Long getUniqueVisitorCountByTimeBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
}
